/*
 * Copyright (c) 2013, TheGhost
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice, this
 *       list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this
 *       list of conditions and the following disclaimer in the documentation and/or other
 *       materials provided with the distribution.
 *     * Neither the name of the product nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior
 *       written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 class Chatserver
 {
 
	channels = [ ];
	
	constructor ( )
	{
		this.loadconfig ( );
		if ( !SERVER.getconfig ( ).defaultchannel )
		{
			local public = getchannel ( "public" );
			local message = "Default channel not set in settings file. ";
			if ( public )
				SERVER.getconfig ( ).defaultchannel = "public";
			else if ( channels.len ( ) >= 1 )
			{
				public = getchannel ( 0 );
				message = message + "Server set default channel to " + public.getname ( ) + ".";
			}
			else
			{
				public = Chatchannel ( "public", "true", "", "Welcome to the default channel.", COLOR[13] );
				channels.push ( public );
				message = message + "No channels were loaded either. Default channel autogenerated and named " + public.getname ( ) + ".";
			}
			log ( message );
		}
	}
	
	function loadconfig ( )
	{
		local toload = [ ];
	
		local xfile = xml ( SERVER.getconfig ( ).chatfile );
		xfile.nodeFirstChild ( );
		while ( true )
		{
			local nodename = xfile.nodeName ( );
			if ( nodename == "channel" )
			{
				local t = { name = xfile.nodeAttribute ( "name" ) };
				xfile.nodeFirstChild ( );
				 
				xfile.nodeFind ( "ispublic" );
				t.ispub <- xfile.nodeContent ( ).tointeger( );
				xfile.nodeParent ( );
				xfile.nodeFind ( "password" );
				t.pass <- xfile.nodeContent ( ).tostring ( );
				xfile.nodeParent ( );
				xfile.nodeFind ( "joinmessage" );
				t.jmsg <- xfile.nodeContent ( ).tostring ( );
				xfile.nodeParent ( );
				xfile.nodeFind ( "color" );
				t.color <- xfile.nodeContent ( ).tointeger ( );
				xfile.nodeParent ( );
				
				toload.push ( t );
			}
			else if ( nodename == "default" )
			{
				SERVER.getconfig ( ).defaultchannel <- xfile.nodeContent( );
			}
			
			if ( !xfile.nodeNext ( ) )
				break;
		}
		
		foreach ( id, channel in toload )
			createchannel ( channel.name, channel.ispub, channel.pass, channel.jmsg, channel.color );
			
		return true;
	}
	
	function createchannel ( name, ispublic = true, pass = false, jmsg = false, color = false )
	{
		local id = channels.len ( );
		local channel = Chatchannel ( id, name, ispublic, pass, jmsg, color )
		channels.push ( channel );
		callEvent ( "channelCreate", channel );
		return channel;
	}
	
	function getchannel ( var )
	{
		if ( typeof ( var ) == "integer" )
			return channels[var];
		else if ( typeof ( var ) == "string" )
		{
			foreach ( id, channel in channels )
			{
				if ( channel.getname ( ) == var )
					return channel;
			}
		}
		return false;
	}
	
	function removechannel ( channel )
	{
		callEvent ( "channelDelete", channel );
		channels.remove ( channel.getid ( ) );
		return true;
	}
	
};
 
class Chatchannel extends Element
{
 
	channelname = "";
	ispublic = true;
	password = false;
	chat = [ ];
	members = [ ];
	logfile = false;
	welcomemessage = "";
	color = 8;
	
	constructor ( id, name, ispublic, pass, jmsg, color )
	{
		this.id = id;
		this.channelname = name;
		this.ispublic = ispublic;
		this.password = pass;
		this.welcomemessage = jmsg;
		this.logfile = Logfile ( channelname );
		this.color = color;
	}
	
	function getname ( )
	{
		return channelname;
	}

	function setname ( name )
	{
		// Need to add file name change
		this.channelname = name;
	}
	
	function isopen ( )
	{
		if ( ispublic == "false" )
			return false;
		else if ( ispublic == "true" )
			return true;
			
		return ispublic;
	}
	
	function close ( )
	{
		this.ispublic = false;
		return true;
	}
	
	function open ( )
	{
		this.ispublic = true;
		return true;
	}
	
	function setpassword ( pass )
	{
		if ( pass != false )
			this.password = pass.tostring ( );
		else
			this.password = false;
		
		return true;
	}
	
	function getpassword ( )
	{
		if ( password == "false" )
			return false;
			
		return password;
	}
	
	function getwelcomemessage ( )
	{
		return welcomemessage;
	}
	
	function setwelcomemessage ( text )
	{
		welcomemessage = text.tostring ( );
		return true;
	}
	
	function getmembers ( )
	{
		return members;
	}
	
	function addmember ( player )
	{
		members.push ( player );
		addchat ( "SERVER", player.getname ( ) + " has entered the chat channel." );
		player.message ( welcomemessage, COLOR[this.color] );
		callEvent ( "channelEnter", this, player );
		return true;
	}
	
	function removemember ( player )
	{
		members.remove ( members.find ( player ) );
		callEvent ( "channelLeave", this, player );
		return true;
	}
	
	function addchat ( sourcename, message )
	{
		local chatline = "[" + channelname + "] " + sourcename + ": " + message.tostring ( );
		chat.push ( chatline );
		
		if ( chat.len ( ) == 20 )
			chat.remove ( 0 );
	
		foreach ( id, player in members )
			player.message ( chatline, COLOR[this.color] );
			
		logfile.writeline ( chatline );
		
		local p = false;
		if ( sourcename == "SERVER" || sourcename == "Console" )
			p = SERVER;
		else
			p = SERVER.getworld ( ).getplayer ( sourcename );
		
		callEvent ( "channelChat", this, p, message );
		return true;
	}
	
	function ismember ( player )
	{
		if ( members.find ( player ) )
			return true;
		
		return false;
	}
	
};
 
class Logfile
{

	filename = false;
	
	constructor ( filename )
	{
		this.filename = filename;
	}
	
	function writeline ( text )
	{
		local xfile = file ( "chatserver/" + filename + ".log", "a+" );
		local stamp = date ( );
		local line = "[" + stamp.hour.tostring ( ) + ":" + stamp.min.tostring ( ) + "] " + text.tostring ( );
		
		foreach ( char in line ) 
			xfile.writen ( char, 'c');	
		
		xfile.writen('\n', 'c');
		log ( line );
		
		return true;
	}
	
};